﻿#region << 版 本 注 释 >>
/*----------------------------------------------------------------
// Copyright (C) 2021 kingerrobot
// 版权所有。 
//
// 文件名：BWcsAsrsCrnInput
// 文件功能描述：
//
// 创建者：名字 (zzl)
// 时间：2021/12/13 14:40:19
//
// 修改人：
// 时间：
// 修改说明：
// 版本：V1.0.0
//----------------------------------------------------------------*/
#endregion
using KingerRobot.MexicoSailunMDC.Dao;
using System.Linq;

namespace KingerRobot.MexicoSailunMDC.SpiService;

internal class BWcsAsrsCrnInput : IWcsAsrsCrnInput
{
    private readonly static IRcsEquipCrn _RcsEquipCrn = new BRcsEquipCrn();
    private readonly static IRcsEquip _RcsEquip = new BRcsEquip();
    private readonly static IRcsLocation _RcsLocation = new BRcsLocation();
    private readonly static ITask _Task = new BTask();
    public List<POWcsAsrsCrnInput> GetWcsAsrsCrnInputs()
    {
        var db = Db.Default;
        var result = db.WcsAsrsCrnInputs.Where(t=>t.UseFlag==1)
            .ToList();
        return result;
    }

    public List<long> GetWcsAsrsCrnInputsByLocIds(List<long?> locIds)
    {


        var db = Db.Default;
        var inputs = db.WcsAsrsCrnInputs.Where(t => t.UseFlag == 1).Select(t => new
        {
            t.InputLoc1,
            t.InputLoc2,
            t.CrnId,
        }).ToList();
        var result = inputs.Where(t => locIds.Contains(t.InputLoc1 ?? 0) || locIds.Contains(t.InputLoc2 ?? 0))
        .Select(t => t.CrnId.GetValueOrDefault())
        .Distinct()
        .ToList();
        return result;

    }
    public POWcsAsrsCrnInput GetWcsAsrsCrnInputsByEquipId(long crnId)
    {

        var db = Db.Default;
        var result = db.WcsAsrsCrnInputs.Where(t => t.CrnId == crnId && t.UseFlag == 1)
            .FirstOrDefault();
        return result;
    }

    public List<POWcsAsrsCrnInput> GetWcsAsrsCrnInputsByEquipIds(List<long?> crnIds)
    {
        var db = Db.Default;
        var inputs = db.WcsAsrsCrnInputs.Where(t => t.UseFlag == 1).ToList();
        var result = inputs.Join(crnIds, f => f.CrnId, s => s, (f, s) => f).ToList();
        return result;
        //return this.GetWcsAsrsCrnInputs().Where(t => crnIds.Contains(t.CrnId)).ToList();
    }

    public POWcsAsrsCrnInput GetWcsAsrsCrnInputByLoc(long loc)
    {
        var db = Db.Default;
        var result = db.WcsAsrsCrnInputs.Where(t => t.InputLoc1 == loc || t.InputLoc2 == loc)
            .FirstOrDefault();
        return result;
    }

    public POWcsAsrsCrnInput GetWcsAsrsCrnInputByLoc(long loc1, long loc2)
    {
        var db = Db.Default;
        var result = db.WcsAsrsCrnInputs.Where(t => t.InputLoc1 == loc1 && t.InputLoc2 == loc2)
            .FirstOrDefault();
        return result;
    }

    public bool HasWcsAsrsCrnInputByLoc(long loc1, long loc2) => GetWcsAsrsCrnInputByLoc(loc1, loc2) is not null;

    public CrnForkBean GetForkByLoc(long loc)
    {
        var db = Db.Default;
        var input = db.WcsAsrsCrnInputs.Where(t => t.InputLoc1 == loc || t.InputLoc2 == loc).FirstOrDefault();
        if (input is null)
        {
            return null;
        }

        var fork = _RcsEquipCrn.GetCrnForkById(input.CrnId);
        if (fork is null)
        {
            return null;
        }

        if (input.InputLoc1 == loc)
        {
            return new()
            {
                CrnId = input.CrnId,
                ForkId = fork.CrnFork1.GetValueOrDefault(),
            };
        }
        if (input.InputLoc2 == loc)
        {
            return new()
            {
                CrnId = input.CrnId,
                ForkId = fork.CrnFork2.GetValueOrDefault(),
            };
        }

        return null;
    }

    /// <summary>
    /// 货叉和堆垛机是否可用(true 有；false 无)
    /// </summary>
    /// <param name="loc"></param>
    /// <returns></returns>
    public bool IsEnableEquip(long loc)
    {
        var fork = GetForkByLoc(loc); // 堆垛机取胎位找货叉
        if (fork == null)
        {
            return false;
        }
        if (!_RcsEquip.IsEnableEquipById(fork.ForkId) || !_RcsEquip.IsEnableEquipById(fork.CrnId))
        {
            // 货叉或堆垛机 异常
            return false;
        }
        return true;
    }


    public List<HasSkuLoc> GetHasSkuLoc(List<long?> crnIds)
    {
        // 根据堆垛机获取入库站台位 LSQ
        var inputs = GetWcsAsrsCrnInputByCrnIds(crnIds);
        if (inputs is null || !inputs.Any())
        {
            return new List<HasSkuLoc>();
        }

        // 一号放胎位；二号放胎位
        var loc1 = inputs.Select(t => t.InputLoc1).ToList();
        var loc2 = inputs.Select(t => t.InputLoc2).ToList();

        var ids = loc1.Union(loc2).ToList();

        // 可用放胎位
        var locations = _RcsLocation.GetLocationsByLocIds(ids);
        var locHasSkus = new List<HasSkuLoc>();

        // 所有输送任务(筛选一下Location绑定的任务Id是否包含在内)
        var taskIds = _Task.GetTaskByType((int)EnumTaskType.Transportation).Select(t => t.Id).ToList();

        // 获取任务物料
        var taskMaterials = _Task.GetTaskMaterial(taskIds);

        inputs.ForEach(item =>
        {
            // 是否绑定胎胚
            var location1 = locations.Where(t => t.Id == item.InputLoc1 && t.TaskId is not null && taskIds.Contains(t.TaskId)).FirstOrDefault();
            var location2 = locations.Where(t => t.Id == item.InputLoc2 && t.TaskId is not null && taskIds.Contains(t.TaskId)).FirstOrDefault();

            var hasSkuLoc = new HasSkuLoc();
            var locBindInfos = new List<LocBindInfo>();


            if (location1 != null)
            {
                var material = taskMaterials.Where(t => t.TaskId == location1.TaskId).FirstOrDefault();

                hasSkuLoc.MinTime = location1.TaskOccupyTime;
                locBindInfos.Add(new()
                {
                    LocId = item.InputLoc1,
                    TaskId = location1.TaskId,
                    MaterialId = material?.MaterialId,
                    LocTime = location1.TaskOccupyTime,
                    HasGood = true,
                    InType = 0,
                    SkuId = material.SkuId,
                    TaskNo = material.TaskNo,
                    Index = 1,
                    Direction = item.Direction,
                    AreaId = item.AreaId,
                    GroupId= material.GroupId
                });
            }

            if (location2 != null)
            {
                var material = taskMaterials.Where(t => t.TaskId == location2.TaskId).FirstOrDefault();

                //OLDTODO 和1物料不同，判断是否有和gongid
                hasSkuLoc.MinTime = hasSkuLoc.MinTime is not null && hasSkuLoc.MinTime.HasValue ?
                hasSkuLoc.MinTime.Value > location2.TaskOccupyTime.Value ?
                location2.TaskOccupyTime.Value : hasSkuLoc.MinTime.Value
                : location2.TaskOccupyTime.Value;

                locBindInfos.Add(new()
                {
                    LocId = item.InputLoc2,
                    TaskId = location2.TaskId,
                    MaterialId = material?.MaterialId,
                    LocTime = location2.TaskOccupyTime,
                    HasGood = true,
                    InType = 0,
                    SkuId = material.SkuId,
                    TaskNo = material.TaskNo,
                    Index = 2,
                    Direction = item.Direction,
                    AreaId= item.AreaId,
                    GroupId = material.GroupId
                });
            }

            if (locBindInfos.Count > 0)
            {
                hasSkuLoc.LocBindInfos = locBindInfos;
                hasSkuLoc.CrnId = item.CrnId;
                hasSkuLoc.AreaId = item.AreaId;
                locHasSkus.Add(hasSkuLoc);
            }
        });

        return locHasSkus;
    }

    private List<POWcsAsrsCrnInput> GetWcsAsrsCrnInputByCrnIds(List<long?> crnIds)
    {
        var db = Db.Default;
        var result = db.WcsAsrsCrnInputs.Where(t => crnIds.Contains(t.CrnId)).ToList();
        return result;
    }

    public int UpdateRemarkByCrnId(long crnId, string remark)
    {
        var db = Db.Default;
        var result = db.WcsAsrsCrnInputs.Where(t => t.CrnId == crnId).Update(new POWcsAsrsCrnInput
        {
            Remark = remark
        });
        return db.SaveChanges();
    }
}

public class HasSkuLoc
{
    /// <summary>
    /// 堆垛机
    /// </summary>
    public long? CrnId { get; set; }
    /// <summary>
    /// 区域
    /// </summary>
    public long? AreaId { get; set; }
    /// <summary>
    /// 最早时间
    /// </summary>
    public DateTime? MinTime { get; set; }
    /// <summary>
    /// 负责站台为
    /// </summary>
    public List<LocBindInfo> LocBindInfos { get; set; }
}
public class LocBindInfo
{
    /// <summary>
    /// 站台位位置ID
    /// </summary>
    public long? LocId { get; set; }
    /// <summary>
    /// 任务ID
    /// </summary>
    public long? TaskId { get; set; }
    /// <summary>
    /// 任务流水号
    /// </summary>
    public int TaskNo { get; set; }
    /// <summary>
    /// 物料ID
    /// </summary>
    public long? MaterialId { get; set; }
    /// <summary>
    /// 绑定时间
    /// </summary>
    public DateTime? LocTime { get; set; }
    /// <summary>
    /// True 有胎；False 无胎
    /// </summary>
    public bool HasGood { get; set; }
    /// <summary>
    /// 序号【1，2】
    /// </summary>
    public int Index { get; set; }

    /// <summary>
    /// 入库类型【0：线体入库；1：手工入库】
    /// </summary>
    public int InType { get; set; } = 0;
    public long SkuId { get; set; }
    /// <summary>
    /// 方向：N（北），S（南）
    /// </summary>
    public string Direction { get; set; }

    public long? AreaId { get; set; }
    /// <summary>
    /// 组号
    /// </summary>
    public int? GroupId { get; set; }
}
